/*
    This file is part of Emu.

    Emu is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Emu is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Emu.  If not, see <http://www.gnu.org/licenses/>. */
#include <QDir>
#include <QDomElement>
#include <QFile>
#include <QTextStream>

#include "esessutils.h"
#include "eprofilewriter.h"

EProfileWriter::EProfileWriter()
{

}

QString EProfileWriter::newProfilePath()
{
    QString pathbase = QDir::homePath() + "/.config/emu/pro_";
    QString retpath;
    int i;

    for (i = 0;i < 100;i++) {
        retpath = pathbase + QString::number(i) + ".epr";
        if (!QFile::exists(retpath))
            return retpath;
    }

    return "";
}

void EProfileWriter::savePrefs(EProfile *p, QString *err)
{
    _profile = p;

    /* If the prefs don't have a profile path, give them one. This happens
       when the profile creator wants a new profile, and when sessions started
       from quick connect want to save a profile. */
    QString path = p->profilePath();
    if (path.isEmpty()) {
        path = newProfilePath();
        if (path.isEmpty()) {
            *err = tr("Too many profiles already exist!");
            return;
        }
        /* Make sure to use the same path next time. */
        p->setProfilePath(path);
    }

    QDomDocument saveDoc("xml");
    _root = saveDoc.createElement("xml");

    saveDoc.appendChild(_root);

    saveSessionData();
    saveAliases();
    saveMacros();
    saveTriggers();
    saveDisplay();

    QFile saveFile(path);

    if (!saveFile.open(QFile::WriteOnly | QFile::Text)) {
        *err = tr("Warning : Failed to save profile of '%1' to '%2'.")
                     .arg(p->title()).arg(path);
        return;
    }

    const int indentSize = 4;

    QTextStream out(&saveFile);
    saveDoc.save(out, indentSize);
    saveFile.close();
}

void EProfileWriter::saveSessionData()
{
    QDomElement sessElem = _saveDoc.createElement("host");

    sessElem.setAttribute("name", _profile->hostName());
    sessElem.setAttribute("address", _profile->hostAddress());
    sessElem.setAttribute("port", _profile->hostPort());

    _root.appendChild(sessElem);
}

void EProfileWriter::saveAliases()
{
    int i;
    QDomElement element;
    QList <EAlias> aliases = _profile->aliases();

    for (i = 0;i < aliases.count();i++) {
        QDomElement element = _saveDoc.createElement("alias");
        QDomElement inputElem = _saveDoc.createElement("input");
        QDomElement outputElem = _saveDoc.createElement("output");
        EAlias alias = aliases.at(i);

        element.setAttribute("name", alias.name());

        QDomText inputText = _saveDoc.createTextNode(alias.input());
        QDomText outputText = _saveDoc.createTextNode(alias.output());

        _root.appendChild(element);

        element.appendChild(inputElem);
        inputElem.appendChild(inputText);

        element.appendChild(outputElem);
        outputElem.appendChild(outputText);
    }
}

void EProfileWriter::saveDisplay()
{
    QDomElement displayElement = _saveDoc.createElement("display");

    /* Save the colors. */

    QStringList colorNames = (QStringList() << "black" << "red" << "green"
     << "yellow" << "blue" << "magenta" << "cyan" << "white" << "boldblack"
     << "boldred" << "boldgreen" << "boldyellow" << "boldblue"
     << "boldmagenta" << "boldcyan" << "boldwhite" << "foreground"
     << "background" << "messageforeground" << "messagebackground");

    int i;
    for (i = 0;i < colorNames.size();i++) {
        QDomElement element = _saveDoc.createElement("color");
        element.setAttribute("name", colorNames[i]);
        element.setAttribute("value", _profile->color(i).name());
        displayElement.appendChild(element);
    }

    _root.appendChild(displayElement);
}

void EProfileWriter::saveMacros()
{
    int i;
    QList <EMacro> macros = _profile->macros();

    for (i = 0;i < macros.count();i++) {
        QDomElement element = _saveDoc.createElement("macro");
        QDomElement inputElem = _saveDoc.createElement("input");
        QDomElement outputElem = _saveDoc.createElement("output");
        QDomElement toElem = _saveDoc.createElement("to");

        EMacro macro = macros.at(i);

        element.setAttribute("name", macro.name());

        QDomText inputText = _saveDoc.createTextNode(
                              ::textFromPress(macro.press()));
        QDomText outputText = _saveDoc.createTextNode(macro.data());
        QDomText toText = _saveDoc.createTextNode(macro.to() == true?
                           "Input Window":"Server");

        _root.appendChild(element);

        element.appendChild(inputElem);
        inputElem.appendChild(inputText);

        element.appendChild(outputElem);
        outputElem.appendChild(outputText);

        element.appendChild(toElem);
        toElem.appendChild(toText);
    }
}

void EProfileWriter::saveTriggers()
{
    QList <ETrigger> triggers = _profile->triggers();
    int i, options;

    for (i = 0;i < triggers.count();i++) {
        QDomElement element = _saveDoc.createElement("trigger");
        QDomElement inputElem = _saveDoc.createElement("input");
        QDomElement outputElem = _saveDoc.createElement("output");
        QDomElement syntaxElem = _saveDoc.createElement("syntax");
        ETrigger trigger = triggers.at(i);
        options = trigger.options();

        element.setAttribute("case_sensitive",
                              trigger.caseSensitivity() == Qt::CaseSensitive?
                              true:false);
        element.setAttribute("name", trigger.name());
        element.setAttribute("keepgoing", !!(options & TRIG_KEEPGOING));

        if (options & TRIG_OMIT)
            element.setAttribute("action", "omit");
        else if (options & TRIG_HIGHLIGHT) {
            element.setAttribute("action", "highlight");
            element.setAttribute("fg", trigger.highlightColor().name());
        }

        QString syntax;

        /* Regexps will be checked for capturing when loaded, so the user can't
           harm them. */
        if (trigger.patternSyntax() == QRegExp::RegExp)
            syntax = "Regular Expression";
        else if (trigger.patternSyntax() == QRegExp::Wildcard)
            syntax = "Wildcard";
        else
            syntax = "Fixed String";

        QDomText inputText = _saveDoc.createTextNode(trigger.pattern());
        QDomText outputText = _saveDoc.createTextNode(trigger.output());
        QDomText syntaxText = _saveDoc.createTextNode(syntax);

        _root.appendChild(element);

        element.appendChild(inputElem);
        inputElem.appendChild(inputText);

        element.appendChild(outputElem);
        outputElem.appendChild(outputText);

        element.appendChild(syntaxElem);
        syntaxElem.appendChild(syntaxText);
    }
}
